<template>
	<view class="vi_month">
		<view class="vi_month_frame">
			<!-- 左侧 -->
			<view class="vi_month_content">
				<view class="vi_month_head" :style="headStyle" v-if="useYear">
					<view class="iconfont" :class="prevCls" @click="turnYear(-1)"></view>
					<view :class="titleClass||''">
						<text @click="openYear()">{{currYear}}</text>
					</view>
					<view class="iconfont" :class="nextCls" @click="turnYear(1)"></view>
				</view>
				<view class="vi_month_list">
					<!-- 选择列表 -->
					<vi-drawer ref="selectList" position="absolute" width="60%" v-if="setting.mode=='checkbox'">
						<scroll-view class="vi_month_selectList" scroll-y @touchmove.stop>
							<view class="vi_month_selectItem" v-for="(item, index) in inValue" :key="index">
								<!-- 标题 -->
								<view class="">
									{{dateFormat(item, useYear?"YYYY-MM":"M"+textSetting.unitMonth)}}
								</view>
								<!-- 删除按钮 -->
								<view @click="delItem(item)">
									<vi-style-controller
										type="bgError"
										radius="circle"
										width="1.2em"
										height="1.2em"
										:disabled="disabled"
										:readOnly="readOnly"
										borderBox
										active>
										<text class="iconfont" :class="iconSetting.delete"></text>
									</vi-style-controller>
								</view>
							</view>
						</scroll-view>
					</vi-drawer>
					
					<view :style="itemStyle" v-for="(item,index) in inList" :key="index">
						<vi-style-controller @click="onClick(item)"
							compName="calendarDate"
							:type="setting.type"
							:color="color"
							:textColor="textColor"
							:radius="item.radius"
							:size="setting.size"
							:plain="plain"
							width="100%"
							:height="setting.rowHeight"
							:borderWidth="plain?1:0"
							:borderColor="item.borderColor"
							:disabled="item.disabled||disabled"
							borderBox
							:active="item.act">
							<text>{{item.name}}{{textSetting.unitMonth}}</text>
						</vi-style-controller>
					</view>
				</view>
			</view>
			<view class="vi_month_to iconfont" :class="iconSetting.to" v-if="setting.mode=='range'"></view>
			<!-- 右侧，选区用 -->
			<view class="vi_month_content" v-if="setting.mode=='range'">
				<view class="vi_month_head" :style="headStyle" v-if="useYear">
					<view class="iconfont" :class="prevCls" @click="turnYear(-1,'end')"></view>
					<view :class="titleClass||''">
						<text @click="openYear('end')">{{currYearEnd}}</text>
					</view>
					<view class="iconfont" :class="nextCls" @click="turnYear(1,'end')"></view>
				</view>
				<view class="vi_month_list">
					<view :style="itemStyle" v-for="(item,index) in inListEnd" :key="index">
						<vi-style-controller @click="onClick(item,'end')"
							compName="calendarDate"
							:type="setting.type"
							:color="color"
							:textColor="textColor"
							:radius="item.radius"
							:size="setting.size"
							:plain="plain"
							width="100%"
							:height="setting.rowHeight"
							:disabled="item.disabled||disabled"
							:active="item.actEnd">
							<text>{{item.name}}{{textSetting.unitMonth}}</text>
						</vi-style-controller>
					</view>
				</view>
			</view>
		</view>
		
		<view class="vi_month_tips" v-if="setting.useToolbar">
			<view class="vi_month_text">
				<view v-if="setting.mode!='checkbox'">
					<text>{{textSetting.monthSelected}}：</text>
				</view>
				<vi-style-controller v-else @click="showSelectList"
					control="text"
					:type="setting.type"
					:color="color"
					:disabled="!inValue.length"
					active>
					<text>{{textSetting.monthSelected}}({{inValue.length}})：</text>
				</vi-style-controller>
			</view>
			<view class="vi_month_info" v-if="setting.mode=='radio'">
				<text>{{dateFormat(inValue[0], useYear?"YYYY-MM":"M"+textSetting.unitMonth)}}</text>
			</view>
			<view class="vi_month_info" v-else-if="setting.mode=='checkbox'">
				<text class="vi_inlineBlock" v-for="(val, index) in inValue" :key="index">{{(index>0?"、":"")+dateFormat(val, useYear?"YYYY-MM":"M"+textSetting.unitMonth)}}</text>
			</view>
			<view class="vi_month_info" v-else-if="setting.mode=='range'">
				{{inValue[0]? dateFormat(inValue[0], useYear?"YYYY-MM":"M"+textSetting.unitMonth) :""}}
				<text class="vi_mx" v-if="inValue.length==2">-</text>
				{{inValue[1]? dateFormat(inValue[1], useYear?"YYYY-MM":"M"+textSetting.unitMonth) :""}}
			</view>
		</view>
		
		<view class="vi_calendar_submitBtn" v-if="setting.useSubmit">
			<vi-button @click="submit"
				:type="setting.type"
				:color="color"
				:textColor="textColor"
				:radius="setting.submitRadius"
				:size="setting.submitSize"
				:plain="submitPlain"
				:width="setting.submitWidth"
				:height="submitHeight"
				:disabled="disabled||disabledSubmit"
				:readOnly="readOnly">{{textSetting.confirm}}</vi-button>
		</view>
		<!-- 年选择器 -->
		<vi-drawer ref="year" point="top">
			<vi-year @change="yearChange" @headClick="closeYear"
				:type="setting.type"
				:color="color"
				:textColor="textColor"
				:radius="setting.radius"
				:size="setting.size"
				:plain="plain"
				:titleHeight="setting.titleHeight"
				:rowHeight="setting.rowHeight"
				:icon="icon"
				:text="textSetting"
				:value="isEnd?currYearEnd:currYear"
				:row="4"
				:column="3"
				:titleClass="titleClass"
				:iconClass="iconClass"
				:start="start"
				:end="end"
				:useSubmit="false"
				:useToolbar="false"
				></vi-year>
		</vi-drawer>
		
	</view>
</template>

<script>
	export default {
		name:"viMonth",
		model:{
			prop:"value",
			event:"input"
		},
		props: {
			type:{
				type:[String,null],
				default:null
			},
			color:{
				type:[String,null],
				default:""
			},
			textColor:{
				type:[String,null],
				default:""
			},
			radius:{
				type:[String,Number,null],
				default:null
			},
			size:{
				type:[String,null],
				default:null
			},
			plain:{
				type:[Boolean,null],
				default:false
			},
			titleHeight:{
				type:[String,null],
				default:""
			},
			rowHeight:{
				type:[String,null],
				default:""
			},
			rowSpace:{
				type:[Number,null],
				default:null
			},
			//选择类型，radio单选、checkbox多选、range选区
			mode:{
				type:[String,null],
				default:""
			},
			value:{},	//当前值，作为基准时间，必须是合法的时间值
			titleClass:{
				type:[String,null],
				default:""
			},
			iconClass:{
				type:[String,null],
				default:""
			},
			//起始范围，开启年选择后必须是时间值，未开启年选择必须是月份值
			start:{
				type:[Number,String,null],
				default:""
			},
			//结束范围，开启年选择后必须是时间值，未开启年选择必须是月份值
			end:{
				type:[Number,String,null],
				default:""
			},
			min:{
				type:[Number,null],
				default:null
			},
			max:{
				type:[Number,null],
				default:0
			},
			//返回数据格式，开启年选择时可选timestamp，ISO，UTC，和自定义格式串。不开启年选择只能返回月份值
			resFormat:{
				type:[String,null],
				default:""
			},
			//使用年选择器
			useYear:{
				type:[Boolean,null],
				default:false
			},
			useToolbar:{
				type:[Boolean,null],
				default:null
			},
			disabled:{
				type:[Boolean,null],
				default:false
			},
			readOnly:{
				type:[Boolean,null],
				default:false
			},
			//提交按钮
			useSubmit:{
				type:[Boolean,null],
				default:null
			},
			submitWidth:{
				type:[String,null],
				default:null
			},
			submitRadius:{
				type:[String,Number,null],
				default:null
			},
			submitSize:{
				type:[String,null],
				default:null
			},
			submitPlain:{
				type:[Boolean,null],
				default:false
			},
			submitHeight:{
				type:[Number,String,null],
				default:""
			},
			icon:{
				type:[Object,null],
				default:()=>({})
			},
			text:{
				type:[Object,null],
				default:()=>({})
			},
		},
		data() {
			return {
				inList:[],		//数据列表
				inValue:[],		//选中列表
				origin:0,		//时间基准点，年变更时才变更
				currYear:0,		//当前年
				inListEnd:[],	//选区结束点，数据列表
				originEnd:0,	//选区结束点，时间基准点
				currYearEnd:0,	//选区结束点，当前年
				isEnd:false,	//是否激活右侧，判断年弹窗数据使用左侧起始月份还是右侧结束月份
				dicIcon:{
					prev: "icon-arr-left",
					next: "icon-arr-right",
					prevYear: "icon-arr-double-left",
					nextYear: "icon-arr-double-right",
					delete: "icon-delete-small",
					to: "icon-arr-double-right",
				},
				dicText:{
					confirm: "确定",
					unitMonth: "月",
					monthSelected: "已选",
					tipMonthEmptyError: "请选择一个选项",
					tipMonthMinError: "请至少选择{$min}个选项",
					tipMonthMaxError: "请选择{$min}至{$max}个选项",
					tipMonthRangeError: "请选择选项范围",
				},
			}
		},
		computed: {
			setting(){
				return {
					type: this.$api.isDefined(this.type)? this.type :"primary",
					mode: this.mode ||"radio",
					min: this.$api.isValue(this.min)? this.min :1,
					size: this.$api.isDefined(this.size)? this.size :"md",
					titleHeight: this.titleHeight ||"2.5em",
					rowHeight: this.rowHeight ||"2.5em",
					radius: this.$api.isDefined(this.radius)? this.radius :"0.25em",
					rowSpace: this.$api.isValue(this.rowSpace)? this.rowSpace :0.2,
					useToolbar: this.$api.isBoolean(this.useToolbar)? this.useToolbar :true,
					useSubmit: this.$api.isBoolean(this.useSubmit)? this.useSubmit :true,
					submitSize: this.$api.isDefined(this.submitSize)? this.submitSize :"md",
					submitRadius: this.$api.isDefined(this.submitRadius)? this.submitRadius :"circle",
					submitWidth: this.$api.isDefined(this.submitWidth)? this.submitWidth :"100%",
					resFormat: this.resFormat ||"timestamp",
				}
			},
			defStart(){
				let res=0,
					start=this.start;
				let temp;
				if(!start){
					return res
				}
				//统一为时间值
				if(String(start).length <=2){//插入年
					temp = new Date();
					temp.setMonth((Number(start)||1) -1);
					res = this.clearDate(temp)
				}else{
					temp = new Date(start)
					res = temp.getTime()? this.clearDate(temp) :0
				}
				return res
			},
			defEnd(){
				let res=Infinity,
					end=this.end;
				let temp;
				if(!end){
					return res
				}
				//统一为时间值
				if(String(end).length <=2){//插入年
					temp = new Date();
					temp.setMonth((Number(end)||1) -1);
					res = this.clearDate(temp)
				}else{
					temp = new Date(end)
					res = temp.getTime()? this.clearDate(temp) :Infinity
				}
				return res
			},
			headStyle(){
				return `height:${this.setting.titleHeight};`
			},
			itemStyle(){
				let res ={
					width:"33.3%"
				};
				res["margin-top"] = (this.setting.rowSpace/2||0) +"em";
				res["margin-bottom"] = (this.setting.rowSpace/2||0) +"em";
				return this.$api.objToStr(res)
			},
			iconSetting(){
				if(this.$api.isObject(this.icon)){
					return Object.assign({},this.dicIcon,this.icon)
				}
				return this.dicIcon
			},
			prevCls(){
				return `${this.iconSetting.prev} ${this.iconClass||""}`
			},
			nextCls(){
				return `${this.iconSetting.next} ${this.iconClass||""}`
			},
			//提交按钮禁用状态
			disabledSubmit(){
				let mode = this.setting.mode;
				if(mode=="radio"){
					return this.inValue.length <1
				}else if(mode=="checkbox"){
					let num = this.inValue.length;
					return (this.setting.min>num)||(this.max&&this.max<=num)||false
				}
				return this.inValue.length !=2
			},
			textSetting(){
				if(this.$api.isObject(this.text)){
					return Object.assign({},this.dicText,this.text)
				}
				return this.dicText
			}
		},
		methods: {
			dateFormat(date, format){
				return this.$api.dateFormat(date, {format})
			},
			//清除时间，日期置1，时间置0
			clearDate(val){
				let tempDate = val? (this.$api.isDate(val)? val :new Date(val)) :new Date();
				//天以下单位清除
				tempDate.setDate(1);
				tempDate.setHours(0);
				let timeStamp =tempDate.getTime();
				return timeStamp - timeStamp%3600000
			},
			openYear(end){
				this.isEnd = !!end;
				this.$refs.year.open();
			},
			//切换年
			turnYear(val, end){
				let target = end? this.originEnd :this.origin;
				this.setOrigin(this.$api.datePoint(target, {year:val}), end);
				this.init()
			},
			//选中年
			yearChange(val){
				let tempDate = new Date(this.curr);
				tempDate.setYear(val);
				let end = this.isEnd;
				setTimeout(()=>{
					this.setOrigin(this.clearDate(tempDate), end);
					this.init();
					let value = this.getData();
					this.$emit("change", value);
					this.$emit("input", value);
					this.$refs.year.close();
				},300)
			},
			//刷新选中年
			setOrigin(val, end){
				if(end){//结束点
					this.originEnd = val;
					this.currYearEnd = val? new Date(val).getFullYear() :""
				}else{//起始点
					this.origin = val;
					this.currYear = val? new Date(val).getFullYear() :""
				}
			},
			//关闭年选择器
			closeYear(){
				this.$refs.year.close()
			},
			//选中月
			onClick(item, end){
				let val =item.value;
				switch(this.setting.mode){
					case "radio":
						this.inValue =[val];
						break;
					case "checkbox":
						let idx = this.inValue.indexOf(val);
						if(idx>-1){//存在则删除
							this.inValue.splice(idx,1)
						}else{
							this.inValue.push(val)
						}
						this.inValue.sort(function(a,b){return a-b});
						break;
					case "range":
						this.$set(this.inValue, end?1:0, val)
						break;
				}
				this.init();
				let value = this.getData();
				this.$emit("change", value);
				this.$emit("input", value);
			},
			//打开选择列表
			showSelectList(){
				this.$refs.selectList.open()
			},
			//删除元素
			delItem(val){
				let idx = this.inValue.indexOf(val);
				if(idx>-1){
					this.inValue.splice(idx,1)
				}
				this.init()
			},
			//生成数据列表
			init(){
				let _this = this;
				//填充左侧
				this.inList =[];
				this.inListEnd =[];
				if(this.setting.mode=="range"){
					_fillList(this.inList, new Date(this.origin), "left");
					_fillList(this.inListEnd, new Date(this.originEnd), "right");
					_checkConnect(this.inListEnd);
				}else{
					//基准点，单选时为选中年，多选时为第一项。无选中为当前年月
					_fillList(this.inList, new Date(this.origin));
				}
				_checkConnect(this.inList);
				function _fillList(list, origin, range){
					for(let i=0; i<12; i++){
						let obj ={name:i+1};
						list.push(obj);
						origin.setMonth(i);
						let val = origin.getTime();
						obj["value"] = val;
						if(val<_this.defStart||val>_this.defEnd){
							obj["disabled"] = true
						}
						if(range){
							let inValue = _this.inValue;
							if(range=="left"){
								if(inValue[0]==val){
									obj["act"] = true
								}
							}else{
								if(inValue[1]==val){
									obj["actEnd"] = true
								}
							}
						}else{
							if(_this.inValue.includes(val)){
								obj["act"] = true
							}
						}
					}
				}
				//检查粘连
				function _checkConnect(list){
					let radius = _this.setting.radius;
					for(let i=0; i<12; i++){
						let R =[radius,radius,radius,radius],
							borderColor ="transparent";
						if(list[i].act){
							borderColor =[null,null,null,null];
							if(i>0&&list[i-1].act){
								R[0] =0;
								R[3] =0;
								borderColor[3] ="transparent";
							}
							if(i<11&&list[i+1].act){
								R[1] =0;
								R[2] =0;
								borderColor[1] ="transparent";
							}
						}
						list[i]["radius"] =R;
						list[i]["borderColor"] = borderColor;
					}
				}
			},
			//外部赋值，校验，统一处理成时间戳
			setValue(newVal){
				let _this = this,
					res =[],
					type = this.$api.typeAsk(newVal),
					value,
					mode = this.setting.mode;
				if(mode=="radio"){
					value = (type=="Array"? _checkValue(newVal[0]) :_checkValue(newVal));
					if(value){
						res = [value]
					}
				}else if(mode=="checkbox"){
					let temp = type=="Array"? newVal :[newVal];
					for(let i=0,len=temp.length; i<len; i++){
						value = _checkValue(temp[i])
						if(value){
							res.push(value)
						}
					}
				}else if(mode=="range"){
					if(type=="Array"&&newVal[0]&&newVal[1]){
						res[0] = _checkValue(newVal[0]);
						res[1] = _checkValue(newVal[1]);
					}
					this.setOrigin(res[1] ||this.clearDate(),"end");
				}
				this.setOrigin(res[0] ||this.clearDate());
				this.inValue = res;
				function _checkValue(val){
					let temp;
					if(!val){
						return null
					}else if(String(val).length <=2){//月份值加入当前年
						temp = new Date();
						temp.setMonth((Number(val)||1) -1);
						return _this.clearDate(temp)
					}else{//其他值转时间格式
						temp = new Date(val);
						return _this.clearDate(temp.getTime()? temp :new Date())
					}
				}
				this.$emit("ready",this.getData());
			},
			//返回数据, 可外部使用
			getData(resFormat){
				resFormat = resFormat || this.setting.resFormat;
				let res =this.$api.clone(this.inValue);
				if(!this.useYear){//不使用年，返回月份
					for(let i=0,len=res.length; i<len; i++){
						res[i] = new Date(res[i]).getMonth() +1
					}
				}else if(resFormat=="timestamp"){//不处理
					
				}else if(resFormat=="ISO"){//返回ISO格式
					for(let i=0,len=res.length; i<len; i++){
						res[i] = new Date(res[i]).toISOString()
					}
				}else if(resFormat=="UTC"){
					for(let i=0,len=res.length; i<len; i++){
						res[i] = new Date(res[i]).toUTCString()
					}
				}else if(typeof(resFormat)=="string"){//自定义格式串
					for(let i=0,len=res.length; i<len; i++){
						res[i] = this.$api.dateFormat(res[i], {format:resFormat})
					}
				}
				//根据选择模式返回
				let mode = this.setting.mode;
				if(mode =="radio"){
					return res[0]
				}else if(mode =="range"){
					//重排序
					res.sort(function(a,b){return a-b});
				}
				return res
			},
			//提交事件
			submit(){
				let len = this.inValue.length;
				let mode = this.setting.mode
					min = this.setting.min,
					max = this.max||0;
				if(mode=="radio" &&len<1){
					this.$api.msg(this.textSetting.tipMonthEmptyError, "error")
					return
				}else if(mode=="checkbox" &&(len<min||(max&&len>max))){
					let msg = max? this.textSetting.tipMonthMaxError :this.textSetting.tipMonthMinError;
					msg = msg.replace("${min}", min);
					msg = msg.replace("${max}", max);
					this.$api.msg(msg, "error")
					return
				}else if(mode=="range" &&len!=2){
					this.$api.msg(this.textSetting.tipMonthRangeError, "error")
					return
				}
				this.$emit("submit", this.getData());
			},
		},
		watch:{
			"value":{
				immediate:true,
				handler(newVal){
					this.setValue(newVal);
					this.init();
				}
			}
		},
	}
</script>

<style lang="scss">
.vi_month{
	transform: translateX(0);
	overflow: hidden;
	.vi_month_frame{
		display: flex;
	}
	.vi_month_content{
		flex-grow: 1;
		&:nth-child(2){
			margin-left: $vi-space-md;
			padding-left: $vi-space-md;
		}
	}
	.vi_month_to{
		align-self: center;
		margin: 0 0.25em;
		color: #999;
	}
	.vi_month_head{
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 0 1em;
		border-bottom: 1px solid $vi-borColor-light;
		.iconfont{
			padding: 0.35em;
		}
	}
	.vi_month_list{
		padding: 0.25em 0;
		display: flex;
		flex-wrap: wrap;
		flex-grow: 1;
		position: relative;
	}
	.vi_mx{
		margin: 0 0.35em;
	}
	.vi_mr{
		margin-right: 0.5em;
	}
	.vi_month_tips{
		line-height: 2.5;
		display: flex;
		align-items: center;
		overflow: hidden;
		.vi_month_text{
			flex-shrink: 0;
		}
	}
	.vi_month_info{
		overflow: hidden;white-space: nowrap;text-overflow: ellipsis;
	}
	.vi_month_selectList{
		height: 100%;
	}
	.vi_month_selectItem{
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin: 0 0.5em;
		padding: 0 0.5em;
		height: 3em;
		&:nth-child(even){
			background-color: #f8f8f8;
		}
	}
	.vi_inlineBlock{
		display: inline-block;
	}
}
</style>
